#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
智能体一键配置工具 - 全新现代版
采用全新的现代化设计理念，提供极致的用户体验
"""

import os
import sys
import tkinter as tk
from tkinter import ttk, messagebox, filedialog, Canvas
import configparser
import winreg
import webbrowser
from pathlib import Path
import subprocess
import threading
import time
from tkinter import font

class ModernConfigTool:
    def __init__(self, root):
        self.root = root
        self.root.title("超级ip智能体配置工具 ")
        self.root.geometry("1200x850")
        self.root.resizable(True, True)
        
        # 现代配色方案
        self.colors = {
            'primary': '#6366f1',        # 主色调 - 靛蓝
            'primary_dark': '#4f46e5',   # 深主色
            'primary_light': '#a5b4fc',  # 浅主色
            'secondary': '#10b981',      # 次要色 - 翠绿
            'accent': '#f59e0b',         # 强调色 - 琥珀
            'danger': '#ef4444',         # 危险色 - 红色
            'bg_main': '#f8fafc',        # 主背景
            'bg_card': '#ffffff',        # 卡片背景
            'bg_hover': '#f1f5f9',       # 悬停背景
            'text_primary': '#0f172a',   # 主文字
            'text_secondary': '#475569', # 次要文字
            'text_muted': '#94a3b8',     # 弱化文字
            'border': '#e2e8f0',         # 边框
            'border_focus': '#6366f1',   # 焦点边框
            'shadow': '#0f172a10'        # 阴影
        }
        
        # 配置变量
        self.install_path = tk.StringVar()
        self.api_key = tk.StringVar()
        self.ffmpeg_path = tk.StringVar()
        self.show_api_var = tk.BooleanVar()
        self.show_output_window = tk.BooleanVar(value=True)  # 默认显示输出窗口
        
        # 进程管理
        self.running_processes = []
        self.is_running = False
        self.cloud_running = False
        
        # 自动检测当前目录和FFmpeg
        self.auto_detect_current_directory()
        self.auto_detect_ffmpeg()
        
        # 设置字体
        self.setup_fonts()
        
        # 设置根窗口样式
        self.root.configure(bg=self.colors['bg_main'])
        
        # 创建界面
        self.create_interface()
        
    def setup_fonts(self):
        """设置字体"""
        self.fonts = {
            'title': ('Segoe UI', 24, 'bold'),
            'subtitle': ('Segoe UI', 14),
            'heading': ('Segoe UI', 16, 'bold'),
            'body': ('Segoe UI', 11),
            'button': ('Segoe UI', 11, 'bold'),
            'small': ('Segoe UI', 10)
        }
        
    def create_interface(self):
        """创建主界面"""
        # 主容器
        main_container = tk.Frame(self.root, bg=self.colors['bg_main'])
        main_container.pack(fill=tk.BOTH, expand=True)
        
        # 顶部导航栏
        self.create_top_nav(main_container)
        
        # 主内容区域
        content_area = tk.Frame(main_container, bg=self.colors['bg_main'])
        content_area.pack(fill=tk.BOTH, expand=True, padx=30, pady=15)
        
        # 创建网格布局
        self.create_grid_layout(content_area)
        
        # 底部操作栏
        self.create_bottom_bar(main_container)
        
    def create_top_nav(self, parent):
        """创建顶部导航栏"""
        nav_frame = tk.Frame(parent, bg=self.colors['primary'], height=80)
        nav_frame.pack(fill=tk.X)
        nav_frame.pack_propagate(False)
        
        # 导航内容
        nav_content = tk.Frame(nav_frame, bg=self.colors['primary'])
        nav_content.pack(fill=tk.BOTH, expand=True, padx=40, pady=0)
        
        # 左侧标题
        title_frame = tk.Frame(nav_content, bg=self.colors['primary'])
        title_frame.pack(side=tk.LEFT, fill=tk.Y)
        
        # 主标题
        title_label = tk.Label(title_frame,
                              text="超级IP智能体配置工具",
                              bg=self.colors['primary'],
                              fg='white',
                              font=self.fonts['title'])
        title_label.pack(side=tk.LEFT, pady=20)
        
        # 右侧状态
        status_frame = tk.Frame(nav_content, bg=self.colors['primary'])
        status_frame.pack(side=tk.RIGHT, fill=tk.Y)
        
        # 状态指示器
        status_indicator = tk.Frame(status_frame, bg='white', width=12, height=12)
        status_indicator.pack(side=tk.RIGHT, padx=(10, 0), pady=34)
        
        status_text = tk.Label(status_frame,
                              text="系统就绪",
                              bg=self.colors['primary'],
                              fg='white',
                              font=self.fonts['body'])
        status_text.pack(side=tk.RIGHT, pady=30)
        
    def create_grid_layout(self, parent):
        """创建网格布局"""
        # 配置网格权重
        parent.grid_columnconfigure(0, weight=1)
        parent.grid_columnconfigure(1, weight=1)
        parent.grid_rowconfigure(0, weight=1)
        parent.grid_rowconfigure(1, weight=1)
        
        # 创建两个主要卡片
        self.create_auto_config_card(parent, 0, 0)  # 左：自动配置
        self.create_api_card(parent, 0, 1)          # 右：API配置
        
    def create_modern_card(self, parent, row, col, title, icon, description=""):
        """创建现代化卡片"""
        # 卡片容器
        card_container = tk.Frame(parent, bg=self.colors['bg_main'])
        card_container.grid(row=row, column=col, padx=10, pady=10, sticky="nsew")
        
        # 主卡片
        card = tk.Frame(card_container,
                       bg=self.colors['bg_card'],
                       relief='flat',
                       bd=0)
        card.pack(fill=tk.BOTH, expand=True)
        
        # 添加阴影效果（通过多层Frame模拟）
        shadow1 = tk.Frame(card_container, bg='#e2e8f0', height=2)
        shadow1.place(relx=0.02, rely=0.02, relwidth=0.98, relheight=0.98)
        
        shadow2 = tk.Frame(card_container, bg='#f1f5f9', height=1)
        shadow2.place(relx=0.01, rely=0.01, relwidth=0.99, relheight=0.99)
        
        card.lift()  # 确保卡片在最上层
        
        # 卡片头部
        header = tk.Frame(card, bg=self.colors['primary'], height=60)
        header.pack(fill=tk.X)
        header.pack_propagate(False)
        
        # 头部内容
        header_content = tk.Frame(header, bg=self.colors['primary'])
        header_content.pack(fill=tk.BOTH, expand=True, padx=20, pady=12)
        
        # 图标
        icon_label = tk.Label(header_content,
                             text=icon,
                             bg=self.colors['primary'],
                             fg='white',
                             font=('Segoe UI', 20))
        icon_label.pack(side=tk.LEFT)
        
        # 标题
        title_label = tk.Label(header_content,
                              text=title,
                              bg=self.colors['primary'],
                              fg='white',
                              font=self.fonts['heading'])
        title_label.pack(side=tk.LEFT, padx=(15, 0))
        
        # 卡片内容区域
        content = tk.Frame(card, bg=self.colors['bg_card'])
        content.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)
        
        # 描述文字
        if description:
            desc_label = tk.Label(content,
                                 text=description,
                                 bg=self.colors['bg_card'],
                                 fg=self.colors['text_secondary'],
                                 font=self.fonts['body'],
                                 wraplength=300,
                                 justify=tk.LEFT)
            desc_label.pack(anchor=tk.W, pady=(0, 20))
        
        return content
        
    def create_auto_config_card(self, parent, row, col):
        """创建自动配置卡片（合并智能体路径和FFmpeg）"""
        content = self.create_modern_card(
            parent, row, col,
            "自动配置",
            "⚙️",
            "自动检测并配置智能体路径和FFmpeg环境"
        )
        
        # 智能体路径部分
        path_section = tk.Frame(content, bg=self.colors['bg_card'])
        path_section.pack(fill=tk.X, pady=(0, 20))
        
        path_title = tk.Label(path_section,
                             text="📁 智能体路径",
                             bg=self.colors['bg_card'],
                             fg=self.colors['text_primary'],
                             font=self.fonts['heading'])
        path_title.pack(anchor=tk.W, pady=(0, 10))
        
        # 状态显示
        path_status_frame = tk.Frame(path_section, bg=self.colors['bg_card'])
        path_status_frame.pack(fill=tk.X, pady=(0, 10))
        
        path_status_icon = tk.Label(path_status_frame,
                                   text="✅",
                                   bg=self.colors['bg_card'],
                                   fg=self.colors['secondary'],
                                   font=('Segoe UI', 14))
        path_status_icon.pack(side=tk.LEFT)
        
        path_status_text = tk.Label(path_status_frame,
                                   text="当前目录已自动检测",
                                   bg=self.colors['bg_card'],
                                   fg=self.colors['secondary'],
                                   font=self.fonts['small'])
        path_status_text.pack(side=tk.LEFT, padx=(8, 0))
        
        # 路径显示框
        self.path_entry = tk.Entry(path_section,
                                  textvariable=self.install_path,
                                  bg='#f8fafc',
                                  fg=self.colors['text_primary'],
                                  font=self.fonts['small'],
                                  relief='solid',
                                  bd=1,
                                  state='readonly',
                                  highlightthickness=0)
        self.path_entry.pack(fill=tk.X, ipady=8)
        
        # 分割线
        separator = tk.Frame(content, bg=self.colors['border'], height=1)
        separator.pack(fill=tk.X, pady=15)
        
        # FFmpeg部分
        ffmpeg_section = tk.Frame(content, bg=self.colors['bg_card'])
        ffmpeg_section.pack(fill=tk.X, pady=(0, 20))
        
        ffmpeg_title = tk.Label(ffmpeg_section,
                               text="🎬 FFmpeg配置",
                               bg=self.colors['bg_card'],
                               fg=self.colors['text_primary'],
                               font=self.fonts['heading'])
        ffmpeg_title.pack(anchor=tk.W, pady=(0, 10))
        
        # FFmpeg状态显示
        ffmpeg_status_frame = tk.Frame(ffmpeg_section, bg=self.colors['bg_card'])
        ffmpeg_status_frame.pack(fill=tk.X, pady=(0, 10))
        
        # 动态检查FFmpeg状态
        ffmpeg_found = bool(self.ffmpeg_path.get() and 
                           self.ffmpeg_path.get() != "未找到FFmpeg" and 
                           os.path.exists(self.ffmpeg_path.get()))
        
        self.ffmpeg_status_icon = tk.Label(ffmpeg_status_frame,
                                          text="✅" if ffmpeg_found else "⚠️",
                                          bg=self.colors['bg_card'],
                                          fg=self.colors['secondary'] if ffmpeg_found else self.colors['accent'],
                                          font=('Segoe UI', 14))
        self.ffmpeg_status_icon.pack(side=tk.LEFT)
        
        self.ffmpeg_status_text = tk.Label(ffmpeg_status_frame,
                                          text="FFmpeg路径已检测" if ffmpeg_found else "FFmpeg路径未找到",
                                          bg=self.colors['bg_card'],
                                          fg=self.colors['secondary'] if ffmpeg_found else self.colors['accent'],
                                          font=self.fonts['small'])
        self.ffmpeg_status_text.pack(side=tk.LEFT, padx=(8, 0))
        
        # FFmpeg路径显示框
        self.ffmpeg_entry = tk.Entry(ffmpeg_section,
                                    textvariable=self.ffmpeg_path,
                                    bg='#f8fafc',
                                    fg=self.colors['text_primary'],
                                    font=self.fonts['small'],
                                    relief='solid',
                                    bd=1,
                                    state='readonly',
                                    highlightthickness=0)
        self.ffmpeg_entry.pack(fill=tk.X, ipady=8)
        
        # 按钮容器
        btn_frame = tk.Frame(content, bg=self.colors['bg_card'])
        btn_frame.pack(fill=tk.X)
        
        # 重新检测按钮
        redetect_btn = tk.Button(btn_frame,
                                text="🔄 重新检测",
                                bg=self.colors['accent'],
                                fg='white',
                                font=self.fonts['button'],
                                relief='flat',
                                bd=0,
                                padx=20,
                                pady=10,
                                cursor='hand2',
                                command=self.redetect_all_paths)
        redetect_btn.pack(side=tk.LEFT, padx=(0, 10))
        
        # 手动选择按钮
        browse_btn = tk.Button(btn_frame,
                              text="📂 手动选择",
                              bg='white',
                              fg=self.colors['text_primary'],
                              font=self.fonts['button'],
                              relief='solid',
                              bd=2,
                              padx=20,
                              pady=10,
                              cursor='hand2',
                              command=self.browse_install_path)
        browse_btn.pack(side=tk.LEFT)
        
    def create_api_card(self, parent, row, col):
        """创建API配置卡片"""
        content = self.create_modern_card(
            parent, row, col,
            "API密钥",
            "🔑",
            "输入智谱AI的API Key，用于智能体功能"
        )
        
        # 按钮容器
        btn_container = tk.Frame(content, bg=self.colors['bg_card'])
        btn_container.pack(fill=tk.X, pady=(0, 15))
        
        # 获取API按钮
        get_api_btn = tk.Button(btn_container,
                               text="🌐 获取API Key",
                               bg=self.colors['secondary'],
                               fg='white',
                               font=self.fonts['small'],
                               relief='flat',
                               bd=0,
                               padx=15,
                               pady=8,
                               cursor='hand2',
                               command=self.open_api_website)
        get_api_btn.pack(side=tk.RIGHT, padx=(10, 0))
        
        # 自动获取当前Key按钮
        auto_get_btn = tk.Button(btn_container,
                                text="🔄 获取当前Key",
                                bg=self.colors['accent'],
                                fg='white',
                                font=self.fonts['small'],
                                relief='flat',
                                bd=0,
                                padx=15,
                                pady=8,
                                cursor='hand2',
                                command=self.auto_get_current_api_key)
        auto_get_btn.pack(side=tk.RIGHT)
        
        # 输入框
        self.api_entry = tk.Entry(content,
                                 textvariable=self.api_key,
                                 bg='white',
                                 fg=self.colors['text_primary'],
                                 font=self.fonts['body'],
                                 relief='solid',
                                 bd=2,
                                 show="*",
                                 highlightthickness=0)
        self.api_entry.pack(fill=tk.X, ipady=12, pady=(0, 10))
        
        # 控制按钮容器
        control_frame = tk.Frame(content, bg=self.colors['bg_card'])
        control_frame.pack(fill=tk.X)
        
        # 显示/隐藏复选框
        show_check = tk.Checkbutton(control_frame,
                                   text="显示密钥",
                                   variable=self.show_api_var,
                                   bg=self.colors['bg_card'],
                                   fg=self.colors['text_secondary'],
                                   font=self.fonts['small'],
                                   command=self.toggle_api_visibility)
        show_check.pack(side=tk.LEFT)
        
        # 单独设置API Key按钮
        set_api_btn = tk.Button(control_frame,
                               text="💾 设置API Key",
                               bg=self.colors['primary'],
                               fg='white',
                               font=self.fonts['small'],
                               relief='flat',
                               bd=0,
                               padx=20,
                               pady=8,
                               cursor='hand2',
                               command=self.set_api_key_only)
        set_api_btn.pack(side=tk.RIGHT)
        
        # 绑定焦点事件
        self.api_entry.bind('<FocusIn>', lambda e: self.on_entry_focus(self.api_entry, True))
        self.api_entry.bind('<FocusOut>', lambda e: self.on_entry_focus(self.api_entry, False))
        
        
        
    def create_bottom_bar(self, parent):
        """创建底部操作栏"""
        # 分隔线
        separator = tk.Frame(parent, bg=self.colors['border'], height=1)
        separator.pack(fill=tk.X)
        
        # 底部操作栏
        bottom_bar = tk.Frame(parent, bg='white', height=70)
        bottom_bar.pack(fill=tk.X)
        bottom_bar.pack_propagate(False)
        
        # 按钮容器
        btn_container = tk.Frame(bottom_bar, bg='white')
        btn_container.pack(expand=True)
        
        # 主要操作按钮
        main_btn = tk.Button(btn_container,
                            text="⚡ 开始一键配置",
                            bg=self.colors['primary'],
                            fg='white',
                            font=('Segoe UI', 14, 'bold'),
                            relief='flat',
                            bd=0,
                            padx=50,
                            pady=15,
                            cursor='hand2',
                            command=self.start_auto_config)
        main_btn.pack(side=tk.LEFT, padx=(0, 20))
        
        # 一键启动/停止按钮
        self.start_stop_btn = tk.Button(btn_container,
                             text="🚀 一键启动",
                             bg=self.colors['secondary'],
                             fg='white',
                             font=('Segoe UI', 14, 'bold'),
                             relief='flat',
                             bd=0,
                             padx=50,
                             pady=15,
                             cursor='hand2',
                             command=self.toggle_digital_human)
        self.start_stop_btn.pack(side=tk.LEFT, padx=10)
        
        # 云连接单一切换按钮
        self.cloud_btn = tk.Button(btn_container,
                                   text="☁️ 启动云连接",
                                   bg=self.colors['primary_dark'],
                                   fg='white',
                                   font=('Segoe UI', 14, 'bold'),
                                   relief='flat',
                                   bd=0,
                                   padx=40,
                                   pady=15,
                                   cursor='hand2',
                                   command=self.start_cloud_connection)
        self.cloud_btn.pack(side=tk.LEFT, padx=10)
        
        # 输出窗口选项（小字体，不明显）
        output_option_frame = tk.Frame(btn_container, bg='white')
        output_option_frame.pack(side=tk.LEFT, padx=(15, 0))
        
        output_check = tk.Checkbutton(output_option_frame,
                                     text="显示命令窗口",
                                     variable=self.show_output_window,
                                     bg='white',
                                     fg=self.colors['text_secondary'],
                                     font=('Segoe UI', 10),
                                     activebackground='white',
                                     activeforeground=self.colors['text_primary'],
                                     selectcolor='white',
                                     relief='flat',
                                     bd=0)
        output_check.pack()
        
        # 添加说明文字
        help_label = tk.Label(output_option_frame,
                             text="(勾选后启动时会显示两个命令窗口)",
                             bg='white',
                             fg=self.colors['text_muted'],
                             font=('Segoe UI', 8))
        help_label.pack()
        
    def on_entry_focus(self, entry, focused):
        """处理输入框焦点事件"""
        if focused:
            entry.config(bd=2, highlightbackground=self.colors['border_focus'])
        else:
            entry.config(bd=1, highlightbackground=self.colors['border'])
            
    def auto_detect_current_directory(self):
        """自动检测当前目录"""
        try:
            # 获取程序所在目录
            if getattr(sys, 'frozen', False):
                # 如果是打包后的exe文件
                current_dir = os.path.dirname(sys.executable)
            else:
                # 如果是Python脚本
                current_dir = os.path.dirname(os.path.abspath(__file__))
            
            # 检查是否存在config.ini文件
            config_file = os.path.join(current_dir, "config.ini")
            if os.path.exists(config_file):
                self.install_path.set(current_dir)
                # 同时自动检测FFmpeg路径
                self.auto_detect_ffmpeg_from_install_path(current_dir)
                return True
            else:
                # 如果当前目录没有config.ini，尝试查找父目录或子目录
                parent_dir = os.path.dirname(current_dir)
                parent_config = os.path.join(parent_dir, "config.ini")
                if os.path.exists(parent_config):
                    self.install_path.set(parent_dir)
                    self.auto_detect_ffmpeg_from_install_path(parent_dir)
                    return True
                    
                # 查找子目录
                for item in os.listdir(current_dir):
                    item_path = os.path.join(current_dir, item)
                    if os.path.isdir(item_path):
                        sub_config = os.path.join(item_path, "config.ini")
                        if os.path.exists(sub_config):
                            self.install_path.set(item_path)
                            self.auto_detect_ffmpeg_from_install_path(item_path)
                            return True
                            
                # 如果都没找到，就使用当前目录
                self.install_path.set(current_dir)
                return False
                
        except Exception as e:
            # 出错时使用当前目录
            current_dir = os.getcwd()
            self.install_path.set(current_dir)
            return False
            
    def redetect_all_paths(self):
        """重新检测所有路径"""
        self.auto_detect_current_directory()
        self.auto_detect_ffmpeg()
        self.update_status_display()
        
    def update_status_display(self):
        """更新状态显示"""
        try:
            ffmpeg_found = bool(self.ffmpeg_path.get() and 
                               self.ffmpeg_path.get() != "未找到FFmpeg" and 
                               os.path.exists(self.ffmpeg_path.get()))
            
            if hasattr(self, 'ffmpeg_status_icon'):
                self.ffmpeg_status_icon.config(
                    text="✅" if ffmpeg_found else "⚠️",
                    fg=self.colors['secondary'] if ffmpeg_found else self.colors['accent']
                )
                
            if hasattr(self, 'ffmpeg_status_text'):
                self.ffmpeg_status_text.config(
                    text="FFmpeg路径已检测" if ffmpeg_found else "FFmpeg路径未找到",
                    fg=self.colors['secondary'] if ffmpeg_found else self.colors['accent']
                )
        except:
            pass
            
    # 以下是功能方法，保持原有逻辑
    def browse_install_path(self):
        """浏览安装路径"""
        path = filedialog.askdirectory(title="选择智能体安装目录")
        if path:
            self.install_path.set(path)
            self.auto_detect_ffmpeg_from_install_path(path)
            
    def browse_ffmpeg_path(self):
        """浏览FFmpeg路径"""
        path = filedialog.askdirectory(title="选择FFmpeg-bin目录")
        if path:
            self.ffmpeg_path.set(path)
            
    def auto_detect_ffmpeg_from_install_path(self, install_path):
        """从安装路径自动检测FFmpeg路径"""
        # 常见的FFmpeg路径模式
        ffmpeg_patterns = [
            "ffmpeg\\bin",
            "tools\\ffmpeg\\bin",
            "bin\\ffmpeg",
            "ffmpeg", "FFmpeg",
            "external\\ffmpeg\\bin",
            "lib\\ffmpeg\\bin"
        ]
        
        # 在安装目录中查找
        for pattern in ffmpeg_patterns:
            full_path = os.path.join(install_path, pattern)
            if os.path.exists(full_path):
                # 检查是否包含ffmpeg.exe
                ffmpeg_exe = os.path.join(full_path, "ffmpeg.exe")
                if os.path.exists(ffmpeg_exe):
                    self.ffmpeg_path.set(full_path)
                    return True
                    
        # 在系统中查找已安装的FFmpeg
        return self.find_system_ffmpeg()
        
    def find_system_ffmpeg(self):
        """在系统中查找已安装的FFmpeg"""
        try:
            # 尝试运行ffmpeg命令来检测是否存在
            result = subprocess.run(['ffmpeg', '-version'], 
                                  capture_output=True, 
                                  text=True, 
                                  timeout=5)
            if result.returncode == 0:
                # FFmpeg在PATH中，查找它的位置
                where_result = subprocess.run(['where', 'ffmpeg'], 
                                            capture_output=True, 
                                            text=True, 
                                            timeout=5)
                if where_result.returncode == 0:
                    ffmpeg_exe_path = where_result.stdout.strip().split('\n')[0]
                    ffmpeg_dir = os.path.dirname(ffmpeg_exe_path)
                    self.ffmpeg_path.set(ffmpeg_dir)
                    return True
        except:
            pass
            
        # 在常见的系统位置查找
        common_paths = [
            "C:\\ffmpeg\\bin",
            "C:\\Program Files\\ffmpeg\\bin",
            "C:\\Program Files (x86)\\ffmpeg\\bin",
            "C:\\tools\\ffmpeg\\bin"
        ]
        
        for path in common_paths:
            if os.path.exists(path):
                ffmpeg_exe = os.path.join(path, "ffmpeg.exe")
                if os.path.exists(ffmpeg_exe):
                    self.ffmpeg_path.set(path)
                    return True
                    
        return False
        
    def auto_detect_ffmpeg(self):
        """自动检测FFmpeg路径"""
        install_path = self.install_path.get()
        
        # 先在安装目录中查找
        if install_path and self.auto_detect_ffmpeg_from_install_path(install_path):
            return True
            
        # 在系统中查找
        if self.find_system_ffmpeg():
            return True
            
        # 都没找到
        self.ffmpeg_path.set("未找到FFmpeg")
        return False
            
    def open_api_website(self):
        """打开API Key获取网站"""
        webbrowser.open("https://open.bigmodel.cn/usercenter/proj-mgmt/apikeys")
        
    def toggle_api_visibility(self):
        """切换API Key显示/隐藏"""
        if self.show_api_var.get():
            self.api_entry.config(show="")
        else:
            self.api_entry.config(show="*")
            
    def auto_get_current_api_key(self):
        """自动获取当前配置文件中的API Key"""
        try:
            install_path = self.install_path.get()
            if not install_path:
                messagebox.showwarning("提示", "请先选择智能体安装目录")
                return
                
            config_file = os.path.join(install_path, "config.ini")
            if not os.path.exists(config_file):
                messagebox.showinfo("提示", "未找到config.ini文件，无法获取当前API Key")
                return
                
            # 读取配置文件
            config = configparser.ConfigParser()
            config.read(config_file, encoding='utf-8')
            
            # 查找API Key
            api_key = None
            for section_name in config.sections():
                section = config[section_name]
                for key in section:
                    if 'api_key' in key.lower():
                        api_key = section[key]
                        break
                if api_key:
                    break
                    
            # 如果在sections中没找到，尝试在DEFAULT section中查找
            if not api_key and config.has_option('DEFAULT', 'api_key'):
                api_key = config.get('DEFAULT', 'api_key')
                
            # 也尝试直接读取文件内容查找
            if not api_key:
                with open(config_file, 'r', encoding='utf-8') as f:
                    content = f.read()
                    import re
                    match = re.search(r'api_key\s*=\s*(.+)', content, re.IGNORECASE)
                    if match:
                        api_key = match.group(1).strip()
                        
            if api_key:
                self.api_key.set(api_key)
                messagebox.showinfo("成功", f"已成功获取当前API Key")
            else:
                messagebox.showinfo("提示", "配置文件中未找到API Key")
                
        except Exception as e:
            messagebox.showerror("错误", f"获取API Key失败：{str(e)}")
            
    def set_api_key_only(self):
        """单独设置API Key到配置文件"""
        try:
            install_path = self.install_path.get()
            api_key = self.api_key.get().strip()
            
            if not install_path:
                messagebox.showwarning("提示", "请先选择智能体安装目录")
                return
                
            if not api_key:
                messagebox.showwarning("提示", "请输入API Key")
                return
                
            config_file = os.path.join(install_path, "config.ini")
            
            if not os.path.exists(config_file):
                # 如果配置文件不存在，创建一个基本的
                with open(config_file, 'w', encoding='utf-8') as f:
                    f.write(f"api_key = {api_key}\n")
                messagebox.showinfo("成功", "API Key已成功设置到新创建的配置文件中")
                return
                
            # 读取现有配置文件
            with open(config_file, 'r', encoding='utf-8') as f:
                lines = f.readlines()
                
            # 查找并更新API Key
            api_key_found = False
            for i, line in enumerate(lines):
                if 'api_key' in line.lower() and '=' in line:
                    lines[i] = f"api_key = {api_key}\n"
                    api_key_found = True
                    break
                    
            # 如果没找到API Key行，添加一行
            if not api_key_found:
                lines.append(f"\napi_key = {api_key}\n")
                
            # 写回文件
            with open(config_file, 'w', encoding='utf-8') as f:
                f.writelines(lines)
                
            messagebox.showinfo("成功", "API Key已成功设置到配置文件中")
            
        except Exception as e:
            messagebox.showerror("错误", f"设置API Key失败：{str(e)}")
            
    def start_auto_config(self):
        """开始一键配置"""
        if not self.validate_inputs():
            return
        
        # 禁用按钮，防止重复点击
        self.disable_config_button()
        
        # 在后台线程中执行配置
        config_thread = threading.Thread(target=self._do_auto_config)
        config_thread.daemon = True
        config_thread.start()
    
    def disable_config_button(self):
        """禁用配置按钮"""
        # 找到配置按钮并禁用
        for widget in self.root.winfo_children():
            if hasattr(widget, 'winfo_children'):
                for child in widget.winfo_children():
                    if hasattr(child, 'winfo_children'):
                        for grandchild in child.winfo_children():
                            if isinstance(grandchild, tk.Button) and "一键配置" in grandchild.cget('text'):
                                grandchild.config(state='disabled', text="⏳ 配置中...")
                                return
    
    def enable_config_button(self):
        """启用配置按钮"""
        # 找到配置按钮并启用
        for widget in self.root.winfo_children():
            if hasattr(widget, 'winfo_children'):
                for child in widget.winfo_children():
                    if hasattr(child, 'winfo_children'):
                        for grandchild in child.winfo_children():
                            if isinstance(grandchild, tk.Button) and ("配置中" in grandchild.cget('text') or "一键配置" in grandchild.cget('text')):
                                grandchild.config(state='normal', text="⚡ 开始一键配置")
                                return
    
    def _do_auto_config(self):
        """在后台线程中执行配置"""
        try:
            # 修改config.ini文件
            self.modify_config_ini()
            
            # 配置环境变量
            self.configure_environment_variables()
            
            # 在主线程中显示成功消息
            self.root.after(0, lambda: self._show_config_success())
                              
        except Exception as e:
            # 在主线程中显示错误消息
            self.root.after(0, lambda: self._show_config_error(str(e)))
    
    def _show_config_success(self):
        """显示配置成功消息"""
        self.enable_config_button()
        messagebox.showinfo("配置完成", 
                          "智能体配置已完成！\n\n"
                          "配置内容：\n"
                          f"• 安装路径：{self.install_path.get()}\n"
                          f"• API Key：{'已设置' if self.api_key.get() else '未设置（可选）'}\n"
                          f"• FFmpeg路径：{self.ffmpeg_path.get()}\n"
                          f"• 环境变量：已配置\n\n"
                          "建议重启相关应用程序以确保配置生效。")
    
    def _show_config_error(self, error_msg):
        """显示配置错误消息"""
        self.enable_config_button()
        messagebox.showerror("配置失败", f"配置过程中出现错误：\n{error_msg}")
            
    def validate_inputs(self):
        """验证用户输入"""
        if not self.install_path.get():
            messagebox.showerror("错误", "请选择智能体安装目录")
            return False
            
        if not os.path.exists(self.install_path.get()):
            messagebox.showerror("错误", "智能体安装目录不存在")
            return False
            
        # API Key不再强制要求，可以为空
        
        if not self.ffmpeg_path.get():
            messagebox.showerror("错误", "请选择FFmpeg路径")
            return False
            
        if not os.path.exists(self.ffmpeg_path.get()):
            messagebox.showerror("错误", "FFmpeg路径不存在")
            return False
            
        return True
        
    def modify_config_ini(self):
        """修改config.ini文件"""
        config_file = os.path.join(self.install_path.get(), "config.ini")
        install_path = self.install_path.get()
        
        if not os.path.exists(config_file):
            # 如果config.ini不存在，创建一个基本的配置文件
            self.create_default_config_ini(config_file, install_path)
            return
            
        try:
            # 读取配置文件
            with open(config_file, 'r', encoding='utf-8') as f:
                lines = f.readlines()
                
            # 修改路径配置（第一个base_dir保留后缀路径，第二个base_dir不保留）
            base_dir_count = 0
            for i, line in enumerate(lines):
                # 查找包含base_dir的行并修改
                if 'base_dir' in line and '=' in line:
                    base_dir_count += 1
                    # 解析原有的路径
                    original_line = line.strip()
                    if '=' in original_line:
                        key_part, value_part = original_line.split('=', 1)
                        value_part = value_part.strip()
                        
                        if base_dir_count == 1:
                            # 第一个base_dir：保留最后一个路径部分
                            if '\\' in value_part or '/' in value_part:
                                # 使用os.path.basename获取最后一个路径部分
                                last_part = os.path.basename(value_part.strip())
                                if last_part:  # 如果有具体的子路径，保留它
                                    lines[i] = f"base_dir = {install_path}\\{last_part}\n"
                                else:  # 如果没有子路径，直接使用安装路径
                                    lines[i] = f"base_dir = {install_path}\n"
                            else:
                                # 如果原路径没有子路径，直接使用安装路径
                                lines[i] = f"base_dir = {install_path}\n"
                        else:
                            # 第二个及以后的base_dir：直接使用安装路径，不保留后缀
                            lines[i] = f"base_dir = {install_path}\n"
                # 查找其他可能的路径配置
                elif 'install_path' in line and '=' in line:
                    lines[i] = f"install_path = {install_path}\n"
                    
            # 添加或修改API Key配置
            api_key_found = False
            for i, line in enumerate(lines):
                if 'api_key' in line.lower() and '=' in line:
                    lines[i] = f"api_key = {self.api_key.get()}\n"
                    api_key_found = True
                    break
                    
            # 只有在API Key不为空时才添加
            if not api_key_found and self.api_key.get():
                lines.append(f"\napi_key = {self.api_key.get()}\n")
                
            # 写回文件
            with open(config_file, 'w', encoding='utf-8') as f:
                f.writelines(lines)
                
        except Exception as e:
            raise Exception(f"修改config.ini文件失败：{str(e)}")
            
    def create_default_config_ini(self, config_file, install_path):
        """创建默认的config.ini文件"""
        default_content = f"""[indexits]
base_dir = {install_path}

[hd_human]
base_dir = {install_path}

api_key = {self.api_key.get() if self.api_key.get() else ''}
"""
        with open(config_file, 'w', encoding='utf-8') as f:
            f.write(default_content)
            
    def configure_environment_variables(self):
        """配置环境变量"""
        try:
            # 打开注册表
            key = winreg.OpenKey(winreg.HKEY_CURRENT_USER, 
                               "Environment", 0, winreg.KEY_ALL_ACCESS)
            
            # 获取当前PATH值
            try:
                current_path, _ = winreg.QueryValueEx(key, "PATH")
            except FileNotFoundError:
                current_path = ""
                
            # 检查FFmpeg路径是否已存在
            ffmpeg_path = self.ffmpeg_path.get()
            if ffmpeg_path and ffmpeg_path not in current_path:
                new_path = f"{current_path};{ffmpeg_path}" if current_path else ffmpeg_path
                winreg.SetValueEx(key, "PATH", 0, winreg.REG_EXPAND_SZ, new_path)
                
            winreg.CloseKey(key)
            
            # 安全地通知系统环境变量已更改
            self._notify_environment_change()
            
        except Exception as e:
            raise Exception(f"配置环境变量失败：{str(e)}")
    
    def _notify_environment_change(self):
        """安全地通知系统环境变量已更改"""
        try:
            import ctypes
            from ctypes import wintypes
            
            # 使用超时的方式发送消息
            def send_message():
                try:
                    # HWND_BROADCAST = 0xFFFF, WM_SETTINGCHANGE = 0x001A
                    result = ctypes.windll.user32.SendMessageTimeoutW(
                        0xFFFF,  # HWND_BROADCAST
                        0x001A,  # WM_SETTINGCHANGE
                        0,       # wParam
                        "Environment",  # lParam
                        2,       # SMTO_ABORTIFHUNG
                        5000,    # 5秒超时
                        None     # pdwResult
                    )
                    return result
                except Exception:
                    # 如果超时版本失败，尝试普通版本（但可能会卡住）
                    try:
                        ctypes.windll.user32.SendMessageW(0xFFFF, 0x001A, 0, "Environment")
                        return True
                    except Exception:
                        return False
            
            # 在一个单独的线程中发送消息，避免阻塞主线程
            import concurrent.futures
            with concurrent.futures.ThreadPoolExecutor() as executor:
                future = executor.submit(send_message)
                try:
                    # 等待最多3秒
                    result = future.result(timeout=3)
                except concurrent.futures.TimeoutError:
                    # 超时也没关系，环境变量已经设置了
                    pass
                    
        except ImportError:
            # 如果没有concurrent.futures，就跳过通知
            pass
        except Exception:
            # 通知失败也没关系，环境变量已经设置了
            pass
            
    def start_digital_human(self):
        """一键启动数字人系统"""
        install_path = self.install_path.get()
        if not install_path or not os.path.exists(install_path):
            messagebox.showerror("错误", "请先配置智能体安装路径")
            return
            
        # 检查bat文件是否存在
        bat1_path = os.path.join(install_path, "01运行数字人后端.bat")
        bat2_path = os.path.join(install_path, "02启动数字人web.bat")
        
        if not os.path.exists(bat1_path):
            messagebox.showerror("错误", f"找不到文件：01运行数字人后端.bat")
            return
            
        if not os.path.exists(bat2_path):
            messagebox.showerror("错误", f"找不到文件：02启动数字人web.bat")
            return
            
        try:
            # 根据用户选择决定是否显示窗口
            import subprocess
            
            # 设置窗口显示标志
            show_window = self.show_output_window.get()
            
            # 显示调试信息
            print(f"启动设置：show_output_window={show_window}")
            
            if show_window:
                # 勾选了"显示命令窗口"，使用start命令来确保窗口显示
                window_msg = "将显示命令窗口"
                
                # 启动后端 - 使用start命令在新窗口中运行
                process1 = subprocess.Popen(
                    f'start "数字人后端" /D "{install_path}" "{bat1_path}"',
                    cwd=install_path,
                    shell=True
                )
                self.running_processes.append(process1)
                
                # 稍微延迟后启动web
                def start_web():
                    process2 = subprocess.Popen(
                        f'start "数字人Web" /D "{install_path}" "{bat2_path}"',
                        cwd=install_path,
                        shell=True
                    )
                    self.running_processes.append(process2)
                    
            else:
                # 没有勾选"显示命令窗口"，隐藏命令窗口
                window_msg = "将隐藏命令窗口"
                
                # 启动后端 - 隐藏窗口
                process1 = subprocess.Popen(
                    bat1_path,
                    cwd=install_path,
                    creationflags=subprocess.CREATE_NO_WINDOW,
                    shell=True
                )
                self.running_processes.append(process1)
                
                # 稍微延迟后启动web
                def start_web():
                    process2 = subprocess.Popen(
                        bat2_path,
                        cwd=install_path,
                        creationflags=subprocess.CREATE_NO_WINDOW,
                        shell=True
                    )
                    self.running_processes.append(process2)
            
            print(f"启动设置：{window_msg}")
                
            self.root.after(2000, start_web)
            
            # 更新按钮状态
            self.is_running = True
            self.start_stop_btn.config(
                text="⏹️ 停止运行",
                bg=self.colors['danger']
            )
            
            # 根据窗口显示设置显示不同的消息
            if show_window:
                messagebox.showinfo("启动成功", "数字人系统已启动！\n\n你应该能看到两个命令窗口正在运行。\n请稍候片刻后访问相应的网址。")
            else:
                messagebox.showinfo("启动成功", "数字人系统已在后台启动！\n\n系统在后台静默运行，没有显示命令窗口。\n请稍候片刻后访问相应的网址。")
            
        except Exception as e:
            messagebox.showerror("启动失败", f"启动数字人系统失败：\n{str(e)}")
            
    def toggle_digital_human(self):
        """切换数字人系统启动/停止状态"""
        if self.is_running:
            self.stop_digital_human()
        else:
            self.start_digital_human()
    
    def start_cloud_connection(self):
        """启动云连接：打开cmd并运行nginx"""
        try:
            nginx_dir = r"C:\nginx\nginx-1.20.2"
            nginx_exe = os.path.join(nginx_dir, "nginx.exe")
            nginx_conf = r"conf\nginx.conf"
            
            # 基础校验
            if not os.path.exists(nginx_dir):
                messagebox.showerror("错误", f"未找到目录：{nginx_dir}")
                return
            if not os.path.exists(nginx_exe):
                messagebox.showerror("错误", f"未找到文件：{nginx_exe}")
                return
            
            show_window = self.show_output_window.get()
            print(f"启动云连接：show_output_window={show_window}")
            
            if show_window:
                # 在新命令行窗口中执行，并保持窗口
                cmd_line = (
                    f'start "云连接" cmd /k "cd /d {nginx_dir} && nginx.exe -c {nginx_conf}"'
                )
                p = subprocess.Popen(cmd_line, shell=True, cwd=nginx_dir)
                self.running_processes.append(p)
                # 获取公网IP并展示可复制地址（不自动打开浏览器）
                url = self._open_cloud_url()
                if url:
                    self.show_copyable_url(url, "启动成功")
                else:
                    messagebox.showinfo("启动成功", "云连接已启动！命令窗口已打开并运行 Nginx。")
            else:
                # 隐藏窗口方式在后台启动
                p = subprocess.Popen(
                    ["cmd", "/c", "nginx.exe", "-c", nginx_conf],
                    cwd=nginx_dir,
                    creationflags=subprocess.CREATE_NO_WINDOW,
                    shell=False
                )
                self.running_processes.append(p)
                # 获取公网IP并展示可复制地址（不自动打开浏览器）
                url = self._open_cloud_url()
                if url:
                    self.show_copyable_url(url, "启动成功")
                else:
                    messagebox.showinfo("启动成功", "云连接已在后台静默启动！")
            # 切换按钮为停止
            self.cloud_running = True
            self.cloud_btn.config(text="⏹️ 停止云连接", bg=self.colors['danger'], command=self.stop_cloud_connection)
        except Exception as e:
            messagebox.showerror("启动失败", f"启动云连接失败：\n{str(e)}")

    def _open_cloud_url(self):
        """获取公网IP并返回 http://<ip>/（不自动打开浏览器）。失败返回None"""
        try:
            ip = self.get_public_ip()
            if ip:
                ip = ip.strip()
                if ip:
                    url = f"http://{ip}/"
                    return url
        except Exception:
            pass
        return None

    def show_copyable_url(self, url, title="信息"):
        """显示可复制URL的自定义对话框"""
        dialog = tk.Toplevel(self.root)
        dialog.title(title)
        dialog.configure(bg='white')
        dialog.resizable(False, False)
        dialog.transient(self.root)
        dialog.grab_set()
        
        container = tk.Frame(dialog, bg='white')
        container.pack(fill=tk.BOTH, expand=True, padx=20, pady=20)
        
        msg = tk.Label(container, text="云连接已启动！\n可复制以下访问地址：", bg='white', fg=self.colors['text_primary'], font=self.fonts['body'], justify=tk.LEFT)
        msg.pack(anchor=tk.W)
        
        entry = tk.Entry(container, bg='#f8fafc', fg=self.colors['text_primary'], relief='solid', bd=1, font=self.fonts['body'])
        entry.pack(fill=tk.X, pady=12, ipady=6)
        entry.insert(0, url)
        entry.select_range(0, tk.END)
        entry.focus_set()
        
        btn_frame = tk.Frame(container, bg='white')
        btn_frame.pack(fill=tk.X)
        
        copied_label = tk.Label(container, text="", bg='white', fg=self.colors['secondary'], font=self.fonts['small'])
        copied_label.pack(anchor=tk.W, pady=(8,0))
        
        def do_copy():
            try:
                self.root.clipboard_clear()
                self.root.clipboard_append(entry.get())
                copied_label.config(text="已复制到剪贴板")
            except Exception:
                pass
        
        copy_btn = tk.Button(btn_frame, text="复制地址", bg=self.colors['primary'], fg='white', font=self.fonts['button'], relief='flat', bd=0, padx=20, pady=8, cursor='hand2', command=do_copy)
        copy_btn.pack(side=tk.LEFT)
        
        close_btn = tk.Button(btn_frame, text="关闭", bg='#e5e7eb', fg=self.colors['text_primary'], font=self.fonts['button'], relief='flat', bd=0, padx=20, pady=8, cursor='hand2', command=dialog.destroy)
        close_btn.pack(side=tk.RIGHT)
        
        # 居中显示弹窗
        dialog.update_idletasks()
        win_w = dialog.winfo_width()
        win_h = dialog.winfo_height()
        root_x = self.root.winfo_x()
        root_y = self.root.winfo_y()
        root_w = self.root.winfo_width()
        root_h = self.root.winfo_height()
        x = root_x + (root_w - win_w) // 2
        y = root_y + (root_h - win_h) // 2
        dialog.geometry(f"{win_w}x{win_h}+{max(x,0)}+{max(y,0)}")

    def stop_cloud_connection(self):
        """停止云连接：优雅退出Nginx (nginx -s quit)"""
        try:
            nginx_dir = r"C:\nginx\nginx-1.20.2"
            nginx_exe = os.path.join(nginx_dir, "nginx.exe")
            if not os.path.exists(nginx_exe):
                messagebox.showwarning("提示", "未检测到 Nginx 安装目录，无法停止。")
                return
            show_window = self.show_output_window.get()
            if show_window:
                # 在新窗口执行停止命令并保持窗口，方便查看结果
                cmd_line = f'start "停止云连接" cmd /k "cd /d {nginx_dir} && nginx.exe -s quit"'
                p = subprocess.Popen(cmd_line, shell=True, cwd=nginx_dir)
                self.running_processes.append(p)
            else:
                # 后台静默停止
                subprocess.Popen(["cmd", "/c", "nginx.exe", "-s", "quit"],
                                 cwd=nginx_dir,
                                 creationflags=subprocess.CREATE_NO_WINDOW,
                                 shell=False)
            messagebox.showinfo("完成", "已发送停止指令（nginx -s quit）。")
            # 切换按钮为启动
            self.cloud_running = False
            self.cloud_btn.config(text="☁️ 启动云连接", bg=self.colors['primary_dark'], command=self.start_cloud_connection)
        except Exception as e:
            messagebox.showerror("停止失败", f"停止云连接失败：\n{str(e)}")

    def get_public_ip(self):
        """优先用curl，其次用PowerShell获取公网IP"""
        try:
            # 尝试使用curl
            r = subprocess.run(["curl", "-s", "ipinfo.io/ip"], capture_output=True, text=True, timeout=5)
            if r.returncode == 0 and r.stdout.strip():
                return r.stdout.strip()
        except Exception:
            pass
        try:
            # PowerShell 兜底方案
            ps_cmd = 'powershell -NoProfile -Command "(Invoke-WebRequest -UseBasicParsing https://ipinfo.io/ip).Content"'
            r = subprocess.run(ps_cmd, capture_output=True, text=True, timeout=7, shell=True)
            if r.returncode == 0 and r.stdout.strip():
                return r.stdout.strip()
        except Exception:
            pass
        return None
            
    def stop_digital_human(self):
        """停止数字人系统"""
        try:
            stopped_count = 0
            
            # 方法1：终止通过subprocess启动的进程
            for process in self.running_processes:
                try:
                    if process.poll() is None:  # 进程还在运行
                        # 终止进程树（包括子进程）
                        self.kill_process_tree(process.pid)
                        stopped_count += 1
                        
                        # 等待一段时间后强制杀死进程
                        try:
                            process.wait(timeout=3)
                        except subprocess.TimeoutExpired:
                            process.kill()  # 强制杀死进程
                except:
                    pass
            
            # 方法2：通过进程名称终止可能遗留的进程
            killed_by_name = self.kill_processes_by_name()
            stopped_count += killed_by_name
                    
            # 清空进程列表
            self.running_processes.clear()
            
            # 更新按钮状态
            self.is_running = False
            self.start_stop_btn.config(
                text="🚀 一键启动",
                bg=self.colors['secondary']
            )
            
            if stopped_count > 0:
                messagebox.showinfo("停止成功", f"已停止 {stopped_count} 个数字人相关进程。")
            else:
                messagebox.showinfo("提示", "没有找到正在运行的数字人进程。")
                
        except Exception as e:
            messagebox.showerror("停止失败", f"停止数字人系统失败：\n{str(e)}")
            # 即使出错也要重置按钮状态
            self.is_running = False
            self.start_stop_btn.config(
                text="🚀 一键启动",
                bg=self.colors['secondary']
            )
    
    def kill_process_tree(self, pid):
        """终止进程树（包括所有子进程）"""
        try:
            import psutil
            parent = psutil.Process(pid)
            children = parent.children(recursive=True)
            
            # 先终止所有子进程
            for child in children:
                try:
                    child.terminate()
                except psutil.NoSuchProcess:
                    pass
            
            # 等待子进程终止
            gone, alive = psutil.wait_procs(children, timeout=3)
            
            # 强制杀死仍然存活的子进程
            for p in alive:
                try:
                    p.kill()
                except psutil.NoSuchProcess:
                    pass
            
            # 最后终止父进程
            try:
                parent.terminate()
                parent.wait(timeout=3)
            except (psutil.NoSuchProcess, psutil.TimeoutExpired):
                try:
                    parent.kill()
                except psutil.NoSuchProcess:
                    pass
                    
        except ImportError:
            # 如果没有psutil，使用系统命令
            try:
                subprocess.run(['taskkill', '/F', '/T', '/PID', str(pid)], 
                             capture_output=True, timeout=10)
            except:
                pass
        except Exception:
            pass
    
    def kill_processes_by_name(self):
        """通过进程名称终止可能的数字人相关进程"""
        killed_count = 0
        
        # 常见的数字人相关进程名称
        process_names = [
            'python.exe', 'pythonw.exe',  # Python进程
            'node.exe',                   # Node.js进程
            'streamlit.exe',              # Streamlit进程
            'gradio.exe',                 # Gradio进程
            'uvicorn.exe',                # Uvicorn进程
            'fastapi.exe'                 # FastAPI进程
        ]
        
        try:
            import psutil
            install_path = self.install_path.get()
            
            for proc in psutil.process_iter(['pid', 'name', 'exe', 'cwd']):
                try:
                    proc_info = proc.info
                    proc_name = proc_info['name'].lower() if proc_info['name'] else ''
                    proc_exe = proc_info['exe'] if proc_info['exe'] else ''
                    proc_cwd = proc_info['cwd'] if proc_info['cwd'] else ''
                    
                    # 检查是否是相关进程且在安装目录下运行
                    if (any(name.lower() in proc_name for name in process_names) and 
                        install_path and install_path.lower() in proc_cwd.lower()):
                        
                        proc.terminate()
                        killed_count += 1
                        
                        # 等待进程终止
                        try:
                            proc.wait(timeout=3)
                        except psutil.TimeoutExpired:
                            proc.kill()
                            
                except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
                    pass
                except Exception:
                    pass
                    
        except ImportError:
            # 如果没有psutil，使用tasklist和taskkill命令
            try:
                install_path = self.install_path.get()
                if install_path:
                    # 查找在安装目录下运行的Python进程
                    result = subprocess.run(['wmic', 'process', 'where', 
                                           f'name="python.exe" and commandline like "%{install_path}%"',
                                           'get', 'processid'], 
                                          capture_output=True, text=True, timeout=10)
                    
                    if result.returncode == 0:
                        lines = result.stdout.strip().split('\n')
                        for line in lines[1:]:  # 跳过标题行
                            if line.strip() and line.strip().isdigit():
                                pid = line.strip()
                                subprocess.run(['taskkill', '/F', '/PID', pid], 
                                             capture_output=True, timeout=5)
                                killed_count += 1
            except Exception:
                pass
        
        return killed_count

    def on_closing(self):
        """程序关闭时的清理工作"""
        # 停止所有运行的进程
        for process in self.running_processes:
            try:
                if process.poll() is None:
                    # 使用新的进程树终止方法
                    self.kill_process_tree(process.pid)
                    try:
                        process.wait(timeout=2)
                    except subprocess.TimeoutExpired:
                        process.kill()
            except:
                pass
        
        # 额外清理可能遗留的进程
        try:
            self.kill_processes_by_name()
        except:
            pass
        
        self.root.quit()
        self.root.destroy()

def main():
    """主函数"""
    root = tk.Tk()
    app = ModernConfigTool(root)
    
    def on_closing():
        root.quit()
        root.destroy()
        
    root.protocol("WM_DELETE_WINDOW", app.on_closing)
    root.mainloop()

if __name__ == "__main__":
    main()
